package com.project.persistence.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

import com.project.persistence.db.Connect;

public abstract class AbstractDAO<T> {

	//TODO acrescentar logs 

	abstract List<T> getAll() ;
	abstract List<T> getAllById(Integer id);
	abstract Boolean insertObject(T t, Connection conn)  throws SQLException;
	abstract Boolean updateObject(T t, Connection conn)  throws SQLException;
	abstract Boolean disableObject(T t, Connection conn)  throws SQLException;
	abstract Boolean enableObject(T t, Connection conn)  throws SQLException;
	abstract T getObject(T t);
	abstract T parseObjectFromRs(ResultSet rs);

	public Boolean insert(T t) {
		Connect connect = new Connect();
		Boolean insertResult = Boolean.FALSE;
		Connection conn = null;
		try {
			
			conn = connect.getConnection();
			openTransaction(conn);
			insertResult = insertObject(t, conn);
			
		} catch (Exception ex) {
			rollback(conn);
			//TODO acrescentar error no log
			ex.printStackTrace();
		} finally {
			commit(conn);
			connect.closeConnection();
		}
		
		return insertResult;
	}

	public Boolean disable(T t) {
		Connect connect = new Connect();
		Boolean disableResult = Boolean.FALSE;
		Connection conn = null;
		try {
			
			conn = connect.getConnection();
			openTransaction(conn);
			
			disableResult = disableObject(t, conn);
			
		} catch (Exception ex) {
			rollback(conn);
			//TODO acrescentar error no log
			ex.printStackTrace();
		} finally {
			commit(conn);
			connect.closeConnection();
		}
		
		return disableResult;
	}
	
	public Boolean enable(T t) {
		Connect connect = new Connect();
		Boolean enableResult = Boolean.FALSE;
		Connection conn = null;
		try {
			
			conn = connect.getConnection();
			openTransaction(conn);
			
			enableResult = enableObject(t, conn);
			
		} catch (Exception ex) {
			rollback(conn);
			//TODO acrescentar error no log
			ex.printStackTrace();
		} finally {
			commit(conn);
			connect.closeConnection();
		}
		
		return enableResult;
	}
	
	public Boolean update(T t) {
		Connect connect = new Connect();
		Boolean updateResult = Boolean.FALSE;
		Connection conn = null;
		try {
			
			conn = connect.getConnection();
			openTransaction(conn);
			
			updateResult = updateObject(t, conn);	
			
		} catch (Exception ex) {
			rollback(conn);
			//TODO acrescentar error no log
			ex.printStackTrace();
		} finally {
			commit(conn);
			connect.closeConnection();
		}
		
		return updateResult;
	}
	
	public Boolean openTransaction(Connection conn) throws SQLException {
		String openTransaction = "START TRANSACTION;";
		PreparedStatement pstm = conn.prepareStatement(openTransaction);
		return pstm.execute(openTransaction);
	}

	public Boolean commit(Connection conn){
		String commit = "COMMIT;";
		Boolean result = Boolean.FALSE;
		PreparedStatement pstm;
		try {
			pstm = conn.prepareStatement(commit);
			result = pstm.execute();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return result;
	}

	public Boolean rollback(Connection conn){
		String commit = "ROLLBACK;";
		Boolean result = Boolean.FALSE;
		PreparedStatement pstm;
		try {
			pstm = conn.prepareStatement(commit);
			result = pstm.execute();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
		return result;
	}
	
}

